package com.baijiayun.live.ui.chat.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.text.style.LineHeightSpan;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import androidx.core.view.GestureDetectorCompat;
import com.baijiayun.live.ui.R;
import com.baijiayun.livecore.context.LPConstants;
import com.baijiayun.livecore.models.imodels.IMessageModel;
import com.baijiayun.liveuibase.utils.DisplayUtils;
import com.baijiayun.liveuibase.utils.RxUtils;
import com.baijiayun.liveuibase.utils.ThemeDataUtil;
import com.baijiayun.liveuibase.widgets.chat.TextLineHeightSpan;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

/**
 * Created by Dujuncan on 2019/2/20
 */
public class ChatMessageView extends LinearLayout {
    private final String TAG = ChatMessageView.class.getCanonicalName();
    public static final String MARK = "-@translate@-";

    private TextView tvMsg;
    private TextView tvTranslateResult;
    private TextView tvReference;
    private LinearLayout messageContainer;
    private LinearLayout btnTranslate;

    private GradientDrawable divideLineDrawable;

    private OnProgressListener onProgressListener;
    private IMessageModel messageModel;
    private boolean isTranslate;
    private boolean isFailed;
    private Disposable subscribeTimer;
    private static int low = 3;

    private GestureDetectorCompat gestureDetectorCompat;
    private TextLineHeightSpan lineHeightSpan;
    public static final int NONE = 0;
    public static final int RECALL = 1;
    public static final int DELETE = 2;
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NONE,RECALL,DELETE})
    public @interface RecallStatus{}

    public ChatMessageView(Context context) {
        this(context, null);
    }

    public ChatMessageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ChatMessageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
        initListener();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ChatMessageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
        initListener();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void init(Context context, AttributeSet attrs) {
        setOrientation(LinearLayout.HORIZONTAL);

        messageContainer = new LinearLayout(context);
        messageContainer.setOrientation(LinearLayout.VERTICAL);
        divideLineDrawable = new GradientDrawable();
        divideLineDrawable.setSize(100, DisplayUtils.dip2px(getContext(), 1));
        messageContainer.setDividerDrawable(divideLineDrawable);
        messageContainer.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
        messageContainer.setPadding(getResources().getDimensionPixelSize(R.dimen.chat_item_text_content_padding_start),
                getResources().getDimensionPixelOffset(R.dimen.chat_item_text_content_padding_top),
                getResources().getDimensionPixelOffset(R.dimen.chat_item_text_content_padding_start),
                getResources().getDimensionPixelOffset(R.dimen.chat_item_text_content_padding_top));
        LayoutParams messageContainerParams = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        messageContainerParams.weight = 1;
        addView(messageContainer, messageContainerParams);

        tvMsg = new TextView(getContext());
        //这里加layoutParams是因为不加有bug。textView测量不准。原因未知
        LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0,5,0,5);
        messageContainer.addView(tvMsg, params);
        final Paint.FontMetricsInt fontMetricsInt = tvMsg.getPaint().getFontMetricsInt();
        lineHeightSpan = new TextLineHeightSpan(fontMetricsInt,20);
        tvMsg.setOnTouchListener((v, event) -> {
            gestureDetectorCompat.onTouchEvent(event);
            return false;
        });

        btnTranslate = new LinearLayout(context);
        btnTranslate.setBackground(ContextCompat.getDrawable(context, R.drawable.bjy_ic_message_translate));
        LayoutParams btnTranslateParams = new LayoutParams(DisplayUtils.dip2px(context, 16), DisplayUtils.dip2px(context, 16));
        btnTranslateParams.setMargins(5, 5, 0, 0);
        addView(btnTranslate, btnTranslateParams);
        btnTranslate.setOnClickListener(v -> {
            if (onProgressListener == null) {
                return;
            }
            btnTranslate.setClickable(false);
            isFailed = false;
            countDown();
            onProgressListener.onProgress();
        });

        tvTranslateResult = new TextView(getContext());

        tvReference = new TextView(getContext());
        tvReference.setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_window_assistant_text_color));
        tvReference.setMaxLines(low);
        tvReference.setEllipsize(TextUtils.TruncateAt.END);
        tvReference.setOnClickListener(v -> {
            if (low == 3) {
                low = Integer.MAX_VALUE;
            } else {
                low = 3;
            }
            tvReference.setMaxLines(low);
        });
    }

    public void setTextColor(int textColor) {
        tvMsg.setTextColor(textColor);
        tvMsg.setLinkTextColor(textColor);
        tvTranslateResult.setTextColor(textColor);
    }

    private void initListener() {
        gestureDetectorCompat = new GestureDetectorCompat(getContext(), new LongPressListener());
    }

    public void enableTranslation(boolean isEnable) {
        if (!isEnable) {
            removeView(btnTranslate);
        }
    }

    public void removeTranslate(){
        if (tvTranslateResult != null){
            messageContainer.removeView(tvTranslateResult);
            tvTranslateResult = null;
            tvTranslateResult = new TextView(getContext());
            tvTranslateResult.setTextColor(tvMsg.getCurrentTextColor());
            isTranslate = false;
        }
        if (subscribeTimer != null && !subscribeTimer.isDisposed()) {
            subscribeTimer.dispose();
        }
        btnTranslate.setClickable(true);
    }

    public void removeReference() {
        if (tvReference != null) {
            messageContainer.removeView(tvReference);
            tvReference = null;
            tvReference = new TextView(getContext());
            tvReference.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            tvReference.setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(getContext(), R.attr.base_theme_window_assistant_text_color));
            tvReference.setMaxLines(low);
            tvReference.setEllipsize(TextUtils.TruncateAt.END);
            tvReference.setOnClickListener(v -> {
                if (low == 3) {
                    low = Integer.MAX_VALUE;
                } else {
                    low = 3;
                }
                tvReference.setMaxLines(low);
            });
        }
    }

    public void setMessageModel(IMessageModel messageModel) {
        this.messageModel = messageModel;
    }


    public void setTranslateButtonVisibility(boolean isVisible) {
        btnTranslate.setVisibility(isVisible? VISIBLE : GONE);
    }


    public void addTranslateMessage(String translateMessage) {
        if (isFailed || isTranslate || translateMessage.equals("")) {
            return;
        }
        if (subscribeTimer != null && !subscribeTimer.isDisposed()) {
            subscribeTimer.dispose();
        }
        if (translateMessage.endsWith("\n")) {
            translateMessage = translateMessage.substring(0, translateMessage.length() - 1);
        }
        tvTranslateResult.setText(translateMessage);
        LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0,5,0,0);
        messageContainer.addView(tvTranslateResult, params);

        isTranslate = true;
        btnTranslate.setClickable(true);
    }

    public void addRefrenceMessage(){
        LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0,0,0,5);
        messageContainer.addView(tvReference,0,params);
    }

    public TextView getTextView() {
        return tvMsg;
    }

    public TextView getTvReference() {
        return tvReference;
    }

    public LineHeightSpan getLineHeightSpan() {
        return lineHeightSpan;
    }

    @SuppressLint("CheckResult")
    private void countDown() {
        //翻译时就开始倒计时，如果倒计时自然结束，显示失败，并打上失败的标签。
        //再次翻译时，再清空标签，重新开始倒计时。
        subscribeTimer = Observable.timer(5000, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(aLong -> {
                    String translateFail = Locale.getDefault().getCountry().equalsIgnoreCase("cn") ? "翻译失败" : "Translate Fail!";
                    tvTranslateResult.setText(translateFail);
                    if (!isTranslate) {
                        LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
                        params.setMargins(0,5,0,5);
                        addView(tvTranslateResult,params);
                    }
                    isFailed = true;
                    btnTranslate.setClickable(true);
                });
    }

    public interface OnProgressListener {
        void onProgress();
    }

    public void setOnProgressListener(OnProgressListener onProgressListener) {
        this.onProgressListener = onProgressListener;
    }

    public void setDivideLineColor(int color) {
        divideLineDrawable.setColor(color);
    }

    public void setMessageContainerBackground(Drawable drawable) {
        messageContainer.setBackground(drawable);
    }

    public boolean isTranslate() {
        return isTranslate;
    }

    class LongPressListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
            if (chatMessageListener != null) {
                chatMessageListener.showMenu((int) e.getRawX(), (int) e.getRawY(), ChatMessageView.this,
                        messageModel, messageModel.getMessageType() == LPConstants.MessageType.Image);
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetectorCompat.onTouchEvent(event);
        return true;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        RxUtils.dispose(subscribeTimer);
        subscribeTimer = null;
    }

    private IChatMessageListener chatMessageListener;

    public void setChatMessageListener(IChatMessageListener chatMessageListener) {
        this.chatMessageListener = chatMessageListener;
    }

    public interface IChatMessageListener {
        /**
         * @param x
         * @param y
         * @param anchorView
         * @param messageModel
         * @param isImage
         */
        void showMenu(int x, int y, View anchorView, IMessageModel messageModel, boolean isImage);
    }
}
